package cn.dapeng.thread.delayedQueue;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

/**
 * @BelongProject study
 * @BelongPackage cn.dapeng.thread.delayedQueue
 * @Description TODO
 * @ClassName TestCase
 * @Author xupenghong
 * @Date 2024/8/28 14:29
 * @Version 1.0.0
 */
public class TestCase {

    /**
     * 自定义延时队列
     *      同步延时队列
     *      非同步延时队列
     */
    public static void main(String[] args) throws Exception {
        long start = System.currentTimeMillis();
        //MyDelayQueueWithoutSyn queue = new MyDelayQueueWithoutSyn(10);
        MyAbstractQueue<Message<Integer>> queue = new MyDelayQueueWithSyn<>(10);
        ExecutorService producer = Executors.newFixedThreadPool(2, new MyThreadFactory());
        for (int i = 0; i < 100; i++) {
            final int index = i;
            int mod = index % 2;
            int random = new Random().nextInt(5);
            final long deadLine = mod == 0 ? 250 * random : 500 * random;
            producer.submit(() -> {
                Message<Integer> m = new Message<>(index, deadLine);
                try {
                    queue.add(m);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });
        }

        ExecutorService consumer = Executors.newSingleThreadExecutor();
        consumer.submit(() -> {
            while (!queue.isEmpty()) {
                try {
                    System.out.println("get => " + queue.take());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        });

        producer.shutdown();
        consumer.shutdown();

        System.out.println(System.currentTimeMillis() - start);
    }

    static class MyThreadFactory implements ThreadFactory {

        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            thread.setDaemon(true);
            return thread;
        }

    }

    static class Message<T> implements MyDelayed {

        long deadLine;

        T t;

        Message(T t, long deadLine) {
            this.t = t;
            setDeadLine(deadLine);
        }

        public void setDeadLine(long deadLine) {
            this.deadLine = deadLine + System.currentTimeMillis();
        }

        public long getDeadLine() {
            return deadLine;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return deadLine - System.currentTimeMillis();
        }

        @Override
        public String toString() {
            return "Message{" +
                    "deadLine=" + deadLine +
                    ", t=" + t +
                    '}';
        }
    }
}
